package org.bridgen.test.compare;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;

import javax.swing.tree.TreeNode;

/**
 * 
 * @author Emma Söderberg <emma add cs.lth.se>
 *
 */

public class Tree implements TreeNode {
	protected Label label;
	protected Forest forest;

	public static Tree create(Forest forest, Label label) {
		return new Tree(forest, label);
	}

	protected Tree(Forest forest, Label label) {
		this.forest = forest;
		this.label = label;
		treeCache = new HashMap<Tree, Integer>();
		if (forest != Forest.empty()) {
			forest.setTopTree(this);
		}
	}

	public Forest forest() {
		return forest;
	}
	public Label label() {
		return label;
	}
	public int degree() {
		return forest.degree();
	}

	public void postOrderList(ArrayList<Tree> list) {
		forest.postOrderList(list);
		list.add(this);
	}

	// Cache

	protected HashMap<Tree,Integer> treeCache;

	public boolean hasCachedValueFor(Tree t) {
		return treeCache.containsKey(t);
	}

	public Integer getCachedValue(Tree t) {
		return treeCache.get(t).intValue();
	}

	public void addCachedValue(Tree t, int value) {
		/* DEBUG System.out.println("Caching distance(" + this + "," + t + ")=" + value); */
		treeCache.put(t, new Integer(value));
	}

	// Empty

	private static final Empty empty = new Empty();
	public static Empty empty() {
		return empty;
	}

	public static class Empty extends Tree {
		private Empty() {
			super(Forest.empty(), Label.empty());
		}
		public String toString() {
			return "empty-tree";
		}
	}
	
	// Print
	
	public String toString() {
		return "tree[" + label.toString() + "]";
	}

	
	
	// Visual display
	
	public Enumeration children() {
		return null;
	}

	public boolean getAllowsChildren() {
		return false;
	}

	public TreeNode getChildAt(int childIndex) {
		return forest.treeList.get(childIndex);
	}

	public int getChildCount() {
		return degree();
	}

	public int getIndex(TreeNode node) {
		int index = forest.treeList.indexOf(node);
		return index >= 0 ? index : 0;
	}

	public TreeNode getParent() {
		return null;
	}

	public boolean isLeaf() {
		return degree() == 0;
	}
}
